package org.xxpay.pay.channel.dwf;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;
import org.xxpay.common.http.HttpRequestTemplate;
import org.xxpay.common.util.DateUtils;
import org.xxpay.common.util.Util;
import org.xxpay.common.util.sign.SignUtils;
import org.xxpay.common.util.str.StringUtils;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.JsonUtil;
import org.xxpay.core.entity.TransOrder;
import org.xxpay.pay.channel.BaseTrans;
import org.xxpay.pay.channel.dwf.util.EncodeUtil;

import java.util.Date;
import java.util.Map;

@Service
public class DwfTransService extends BaseTrans {

    private final static String logPrefix = "【DWF代付】";

    // 下单地址
    public static final String ORDER_CREATE_STR = "/102002.pay";
    // 查单地址
    private final static String ORDER_QUERY_STR = "/102020.pay";
    // 余额查询地址
    private final static String ORDER_BALANCE_STR = "/102005.pay";


    @Override
    public String getChannelName() {
        return DwfConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject balance(String payParam) {
        Map<String, Object> params = Maps.newHashMap();
        buildTransBalanceParams(params);
        DwfConfig dwfConfig = new DwfConfig(payParam);
        Map<String, Object> commonParam = getCommonParam(null, dwfConfig, "102005");
        params.put("head", commonParam);
        _log.info("{}余额查询请求参数：{}", logPrefix, JsonUtil.object2Json(params));
        String encryptData = getEncryptData(params, dwfConfig);
        String sign = getSign(params, dwfConfig);
        Map<String, Object> reqMap = Maps.newHashMap();
        reqMap.put("partnerNo", dwfConfig.getMchId());
        reqMap.put("encryptData", encryptData);
        reqMap.put("signData", sign);
        _log.info("{}余额查询最终请求报文：{}", logPrefix, JSON.toJSONString(reqMap));

        HttpRequestTemplate requestTemplate = new HttpRequestTemplate(null);
        String origin = requestTemplate.postForObject(getReqUrl(dwfConfig.getRequestUrl(), ORDER_BALANCE_STR), reqMap, String.class);
        JSONObject resObject = JsonUtil.getObjectFromJson(origin, JSONObject.class);
        String resEncryptData = resObject.getString("encryptData");
        String privateKey = dwfConfig.getPrivateKey();
        String plainText = EncodeUtil.decode(resEncryptData, privateKey.substring(0, 16));
        _log.info("{}余额查询响应参数：{}", logPrefix, plainText);
        JSONObject resData = JsonUtil.getJSONObjectFromJson(plainText);
        JSONObject retObj = buildRetObj();
        retObj.put("cashBalance", Util.conversionYuanAmount(resData.getLong("availableBalance")));
        retObj.put("payBalance", Util.conversionYuanAmount(resData.getLong("totalBalance")));
        return retObj;
    }

    @Override
    public JSONObject trans(TransOrder transOrder) {
        Map<String, Object> params = Maps.newHashMap();
        buildTransReqParams(params, transOrder);
        DwfConfig dwfConfig = new DwfConfig(getTransParam(transOrder));
        Map<String, Object> commonParam = getCommonParam(transOrder, dwfConfig, "102002");
        params.put("head", commonParam);
        _log.info("{}申请代付请求参数：{}", logPrefix, params.toString());
        String encryptData = getEncryptData(params, dwfConfig);
        String sign = getSign(params, dwfConfig);
        Map<String, Object> reqMap = Maps.newHashMap();
        reqMap.put("partnerNo", dwfConfig.getMchId());
        reqMap.put("encryptData", encryptData);
        reqMap.put("signData", sign);
        _log.info("{}申请代付最终请求报文：{}", logPrefix, JSON.toJSONString(reqMap));
        HttpRequestTemplate requestTemplate = new HttpRequestTemplate(null);
        String origin = requestTemplate.postForObject(getReqUrl(dwfConfig.getRequestUrl(), ORDER_CREATE_STR), reqMap, String.class);
        JSONObject resObject = JsonUtil.getObjectFromJson(origin, JSONObject.class);
        String resEncryptData = resObject.getString("encryptData");
        String privateKey = dwfConfig.getPrivateKey();
        String plainText = EncodeUtil.decode(resEncryptData, privateKey.substring(0, 16));
        _log.info("{}请求响应参数：{}", logPrefix, plainText);
        JSONObject resData = JsonUtil.getJSONObjectFromJson(plainText);
        JSONObject retObj = buildRetObj();
        JSONObject headObject = JSONObject.parseObject(resData.getString("head"));
        if (StringUtils.equals(headObject.getString("respCode"), "000000")){
            retObj.put("transOrderId", transOrder.getTransOrderId());
            retObj.put("channelOrderNo", headObject.getString("platformId"));
            retObj.put("status", 1); // 1表示处理中
            retObj.put("isSuccess", true);
            return retObj;
        }
        retObj.put("status", 3);
        retObj.put(PayConstant.RESULT_PARAM_ERRDES, "下单失败[" + headObject.getString("respMsg") + "]");
        retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_FAIL);
        retObj.put("channelErrCode", headObject.getString("respMsg"));
        retObj.put("isSuccess", false); // 3表示失败
        return retObj;
    }

    @Override
    public JSONObject query(TransOrder transOrder) {
        Map<String, Object> params = Maps.newHashMap();
        buildTransQueryReqParams(params, transOrder);
        DwfConfig dwfConfig = new DwfConfig(getTransParam(transOrder));
        Map<String, Object> commonParam = getCommonParam(transOrder, dwfConfig, "102020");
        params.put("head", commonParam);
        _log.info("{}查询请求参数：{}", logPrefix, JsonUtil.object2Json(params));
        String encryptData = getEncryptData(params, dwfConfig);
        String sign = getSign(params, dwfConfig);
        Map<String, Object> reqMap = Maps.newHashMap();
        reqMap.put("partnerNo", dwfConfig.getMchId());
        reqMap.put("encryptData", encryptData);
        reqMap.put("signData", sign);
        _log.info("{}查询最终请求报文：{}", logPrefix, JSON.toJSONString(reqMap));

        HttpRequestTemplate requestTemplate = new HttpRequestTemplate(null);
        String origin = requestTemplate.postForObject(getReqUrl(dwfConfig.getRequestUrl(), ORDER_QUERY_STR), reqMap, String.class);
        JSONObject resObject = JsonUtil.getObjectFromJson(origin, JSONObject.class);
        String resEncryptData = resObject.getString("encryptData");
        String privateKey = dwfConfig.getPrivateKey();
        String plainText = EncodeUtil.decode(resEncryptData, privateKey.substring(0, 16));
        _log.info("{}请求响应参数：{}", logPrefix, plainText);
        JSONObject resData = JsonUtil.getJSONObjectFromJson(plainText);
        String headString = resData.getString("head");
        JSONObject headObject = JSONObject.parseObject(headString);
        JSONObject retObj = new JSONObject();
        if(org.apache.commons.lang3.StringUtils.equals(headObject.getString("respCode"), "000000")) {
            retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_SUCCESS);
            retObj.put("isSuccess", true);
            retObj.putAll(resData);
            retObj.put("transOrderId", transOrder.getTransOrderId());
            String orderStatus = resData.getString("orderStatus");
            /**
             * 01-提现成功
             * 02-提现失败
             * 04-提现中
             */
            if (StringUtils.equals(orderStatus,"01")) {
                retObj.put("status", 2); // 2表示成功
            } else if (StringUtils.equals(orderStatus,"02")) {
                retObj.put("status", 3); // 3表示失败
            } else {
                retObj.put("status", 1); // 1处理中
            }
            retObj.put("channelObj", resData);
            return retObj;
        }
        retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_FAIL);
        retObj.put(PayConstant.RESULT_PARAM_ERRDES, String.format("code:%s,desc:%s", headObject.getString("respCode"), headObject.getString("respMsg")));
        retObj.put("channelErrCode", headObject.getString("respMsg"));
        retObj.put("isSuccess", false);
        return retObj;
    }

    private void buildTransBalanceParams(Map<String, Object> params){
        params.put("messyCode", "aaaaaaaaaaaaaaaaaa");
    }

    private void buildTransReqParams(Map<String, Object> params, TransOrder transOrder){
        params.put("amount", transOrder.getAmount());
        params.put("bankAccountName", transOrder.getAccountName());
        params.put("bankAccountNo", transOrder.getAccountNo());
        params.put("bankAccountType", "PRIVATE");
        params.put("bankName", transOrder.getBankName());
        params.put("provice", transOrder.getProvince());
        params.put("city", transOrder.getCity());
    }

    private void buildTransQueryReqParams(Map<String, Object> params, TransOrder transOrder){
        params.put("oriTraceId", transOrder.getTransOrderId());
    }

    private Map<String, Object> getCommonParam(TransOrder transOrder, DwfConfig dwfConfig, String txnCode){
        Map<String, Object> params = Maps.newHashMap();
        params.put("version", "1.0.0");
        params.put("charset", SignUtils.CHARSET_UTF8);
        params.put("partnerNo", dwfConfig.getMchId());
        params.put("partnerType", "OUTER");
        params.put("txnCode", txnCode);
        if (transOrder != null){
            params.put("traceId", transOrder.getTransOrderId());
        }
        Date now = new Date();
        params.put("reqDate", DateUtils.YYYYMMDD.format(now));
        params.put("reqTime", DateUtils.YYYYMMDDHHMMSS.format(now));
        return params;
    }

    private String getEncryptData(Map<String, Object> params, DwfConfig dwfConfig) {
        String aesKey = dwfConfig.getPrivateKey().substring(0, 16);
        String planText = JsonUtil.object2Json(params);
        _log.info("{}请求参数：{}", logPrefix, planText);
        return EncodeUtil.encode(planText, aesKey);
    }

    private String getSign(Map<String, Object> params, DwfConfig dwfConfig) {
        String sha1Key = dwfConfig.getPrivateKey().substring(16);
        String jsonBody = JsonUtil.object2Json(params);
        return DigestUtils.sha1Hex(jsonBody+sha1Key);
    }

}
